<?php
/**
 * CK 开发框架
 * User: Clake
 * Date: 15/7/29
 * Time: 23:58
 */

namespace CK\Util;


class Http {

    /**
     * HTTP 访问URL地址并返回结果
     * @param string $url
     * @param string $post
     * @param array  $headers
     * @param array  $extra
     * @param int    $timeout
     *
     * @return array|bool
     */
    public static function request($url, $post = '', $headers = [], $timeout = 60,$extra = []) {
        $urlset = parse_url($url);
        if(empty($urlset['path'])) {
            $urlset['path'] = '/';
        }
        if(!empty($urlset['query'])) {
            $urlset['query'] = "?{$urlset['query']}";
        } else {
            $urlset['query'] = '';
        }
        if(empty($urlset['port'])) {
            $urlset['port'] = '80';
        }

        if(function_exists('curl_init') && function_exists('curl_exec')) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $urlset['scheme']. '://' .$urlset['host'].($urlset['port'] == '80' ? '' : ':'.$urlset['port']).$urlset['path'].$urlset['query']);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, 1);
            if($post) {
                curl_setopt($ch, CURLOPT_POST, 1);
                if (is_array($post)) {
                    $post = http_build_query($post);
                }
                curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
            }
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1');
            if (!empty($extra) && is_array($extra)) {
                foreach ($extra as $opt => $value) {
                    if (strpos($opt, 'CURLOPT_')) {
                        curl_setopt($ch, constant($opt), $value);
                    }
                    if (is_numeric($opt)) {
                        curl_setopt($ch, $opt, $value);
                    }
                }
            }
            if (!empty($headers) && is_array($headers)) {
                $headers[]  =  'Expect:';
            }
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            $data = curl_exec($ch);
            $status = curl_getinfo($ch);
            $errno = curl_errno($ch);
            curl_close($ch);
            if($errno || empty($data)) {
                return false;
            } else {
                return Http::response_parse($data);
            }
        }
        $method = empty($post) ? 'GET' : 'POST';
        $fdata = "{$method} {$urlset['path']}{$urlset['query']} HTTP/1.1\r\n";
        $fdata .= "Host: {$urlset['host']}\r\n";
        if(function_exists('gzdecode')) {
            $fdata .= "Accept-Encoding: gzip, deflate\r\n";
        }
        $fdata .= "Connection: close\r\n";
        if (!empty($extra) && is_array($extra)) {
            foreach ($extra as $opt => $value) {
                if (!strexists($opt, 'CURLOPT_')) {
                    $fdata .= "{$opt}: {$value}\r\n";
                }
            }
        }
        $body = '';
        if ($post) {
            if (is_array($post)) {
                $body = http_build_query($post);
            } else {
                $body = urlencode($post);
            }
            $fdata .= 'Content-Length: ' . strlen($body) . "\r\n\r\n{$body}";
        } else {
            $fdata .= "\r\n";
        }
        $fp = fsockopen($urlset['host'], $urlset['port']);
        stream_set_blocking($fp, true);
        stream_set_timeout($fp, $timeout);
        if (!$fp) {
            return false;
        } else {
            fwrite($fp, $fdata);
            $content = '';
            while (!feof($fp))
                $content .= fgets($fp, 512);
            fclose($fp);
            return Http::response_parse($content);
        }
    }

    /**
     * 解释返回的数据
     * @param $data
     *
     * @return array
     */
    public static function response_parse($data) {
        $rlt = array();
        $pos = strpos($data, "\r\n\r\n");
        $split1[0] = substr($data, 0, $pos);
        $split1[1] = substr($data, $pos + 4, strlen($data));

        $split2 = explode("\r\n", $split1[0], 2);
        preg_match('/^(\S+) (\S+) (.*?)$/', $split2[0], $matches);
        $rlt['code'] = $matches[2];
        $rlt['status'] = $matches[3];
        $rlt['responseline'] = $split2[0];
        $rlt['headers'] = [];
        $header = explode("\r\n", $split2[1]);
        $isgzip = false;
        foreach ($header as $v) {
            $row = explode(':', $v);
            $key = trim($row[0]);
            $value = trim($row[1]);
            if (isset($rlt['headers'][$key]) &&
                is_array($rlt['headers'][$key])) {
                $rlt['headers'][$key][] = $value;
            } elseif (!empty($rlt['headers'][$key])) {
                $temp = $rlt['headers'][$key];
                unset($rlt['headers'][$key]);
                $rlt['headers'][$key][] = $temp;
                $rlt['headers'][$key][] = $value;
            } else {
                $rlt['headers'][$key] = $value;
            }
            if(!$isgzip && strtolower($key) == 'content-encoding' && strtolower($value) == 'gzip') {
                $isgzip = true;
            }
        }
        if($isgzip && function_exists('gzdecode')) {
            $rlt['content'] = gzdecode($split1[1]);
        } else {
            $rlt['content'] = $split1[1];
        }
        $rlt['meta'] = $data;
        return $rlt;
    }

    /**
     * 用GET方式访问HTTP地址
     * @param $url
     *
     * @return array|bool
     */
    public static function get($url) {
        return Http::request($url);
    }

    /**
     * 用POST方式访问HTTP地址
     * @param $url
     * @param $data
     *
     * @return array|bool
     */
    public static function post($url, $data) {
        $headers = ['Content-Type: application/x-www-form-urlencoded'];
        return Http::request($url, $data, $headers, 30);
    }

    public static function post_json($url,$data) {
        $headers = ['Content-Type:application/json','charset=utf-8'];
        return Http::request($url, json_encode($data), $headers, 30);
    }
}